import i18n from '@/i18n'
import { useApi } from '@/api'
import { useMessage } from '@/main'
import { FileType, GetNasFileListParams, GetNasFileListResponse, NasFile } from '@global/types'
import { defineStore } from 'pinia'
import { onMounted, Ref, watch } from 'vue'
import { useEnv } from './useEnv'
import useUserInfo from './useUserInfo'
import { random } from 'lodash'

export type MusicPlayMode = 'single' | 'order' | 'cycle' | 'random'

const t = i18n.global.t

export const useMusic = defineStore('music', {
  state: () => ({
    /** 显示音乐播放器 */
    show: false,
    /** 是否处于播放状态 */
    isPlay: false,
    /** 播放模式：single单曲播放，order顺序播放，cycle单曲循环，random随机播放 */
    playMode: 'single' as MusicPlayMode,
    /** 当前播放时间 */
    currentTime: 0,
    /** 音乐总时长 */
    totalTime: 0,
    /** 当前音乐索引 */
    index: 0,
    /** 用户所有音乐文件列表 */
    musicList: [] as NasFile[],
    /** audio元素 */
    musicRef: null as HTMLAudioElement | null
  }),
  getters: {
    /** 获取当前音乐文件信息 */
    getCurrentMusicInfo: state => {
      if (state.musicList.length) return { ...state.musicList[state.index], i: state.index }
      return null
    },
    /** 获取音乐文件地址 */
    getAudioSrc: state => {
      const filePath = state.musicList[state.index]?.filePath
      if (!filePath) return ''
      return encodeURI(`${useEnv().staticUrl}/users/${useUserInfo().id}/nas/file/${filePath}`)
    },
    /** 获取上一首音乐文件信息 */
    getLastMusicInfo: state => {
      if (!state.index) return state.musicList[state.musicList.length - 1]
      const i = state.index - 1
      return state.musicList[i]
    },
    /** 获取下一首音乐文件信息 */
    getNextMusicInfo: state => {
      const i = state.index + 1
      if (!state.musicList[i]) return state.musicList[0]
      return state.musicList[i]
    }
  },
  actions: {
    /** 更新用户的所有音乐文件列表 */
    async updateMusicList() {
      const res: GetNasFileListResponse = await useApi().get('/nas/list', {
        params: {
          page: 1,
          size: 2 ** 31,
          fileType: FileType.audio
        } as GetNasFileListParams
      })
      const musicList = res.list
      this.musicList = musicList
    },
    /** 播放当前索引所在的音乐 */
    play() {
      setTimeout(() => this.musicRef!.play())
    },
    /** 暂停播放 */
    pause() {
      this.musicRef!.pause()
    },
    /** 根据ID选择音乐文件 */
    selectMusic(id: number) {
      this.index = this.musicList.findIndex(item => item.id === id)
      this.show = true
      this.play()
    },
    /** 播放上一首 */
    playLast() {
      const newIndex = this.index ? this.index - 1 : this.musicList.length - 1
      if (newIndex === this.index) return useMessage().warning(t('only-one-music'))
      this.index = newIndex
      this.play()
    },
    /** 播放下一首 */
    playNext() {
      let newIndex = this.index + 1
      if (!this.musicList[newIndex]) newIndex = 0
      if (newIndex === this.index) return useMessage().warning(t('only-one-music'))
      this.index = newIndex
      this.play()
    }
  }
})

/** 初始化音乐 */
export const initMusic = (musicRef: Ref<HTMLAudioElement>) => {
  onMounted(() => {
    music.musicRef = musicRef.value
  })
  const music = useMusic()
  // 音乐播放器显隐时更新音乐列表
  watch(() => music.show, music.updateMusicList)
  // 音乐列表为空时隐藏音乐播放器，暂停播放音乐
  watch(
    () => music.musicList,
    list => {
      if (!list.length) {
        music.$patch({ show: false, isPlay: false })
        musicRef.value.pause()
      }
    }
  )
  watch(
    () => useUserInfo().token,
    token => {
      if (!token) music.$patch({ show: false, isPlay: false })
    }
  )
  // 监听播放模式
  watch(
    () => music.playMode,
    mode => {
      let playEndedAction: () => void = () => undefined
      musicRef.value.loop = mode === 'cycle'
      if (mode === 'order') playEndedAction = () => music.playNext()
      if (mode === 'random')
        playEndedAction = () => {
          music.index = random(music.musicList.length - 1)
          music.play()
        }
      musicRef.value.onended = () => {
        music.$patch({ isPlay: false })
        playEndedAction()
      }
    }
  )
}
